package com.bdcom.autotest.telnet;

import com.bdcom.autotest.telnet.constant.TelnetConstant;
import com.bdcom.autotest.telnet.model.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class TelnetCommunication implements TelnetConstant {
    private static Logger log = LoggerFactory.getLogger(TelnetCommunication.class);
    private String connectWithRetry( TelnetClientForCOM client , long time , int retryTime) throws Exception{

        String connect = client.connect(time);
        if( connect.toLowerCase().contains("username") ||connect.contains("")|| connect.contains(ENTER_COMMAND_ARROW) ){
            return connect;
        }
        //重试
        while( retryTime>0 ){
            connect += client.getResponse(time);
            if( connect.toLowerCase().contains("username") ||connect.contains("")|| connect.contains(ENTER_COMMAND_ARROW) ){
                return connect;
            }
            retryTime--;
        }
        return null;
    }

    public String sendCommandWithRetry( TelnetClientForCOM client , long time , int retryTime ,String cmd , List<String> endFlags) throws Exception{
        String resultStr = client.sendCommand(cmd, time);
       for (String endFlag:endFlags){
           String lowerCase = endFlag.toLowerCase();
           if( resultStr.toLowerCase().contains(lowerCase) ){
               return resultStr;
           }
       }

        //重试
        while( retryTime>0 ){
            resultStr += client.getResponse(time);
            for (String endFlag:endFlags){
                String lowerCase = endFlag.toLowerCase();
                if( resultStr.toLowerCase().contains(lowerCase) ){
                    return resultStr;
                }
            }

            retryTime--;
        }
        return resultStr;

    }

    public String sendReboot( TelnetClientForCOM client ) throws Exception{
        String resultStr = client.sendCommand("y", EXEC_REBOOT_TIME);
        if( resultStr.toLowerCase().contains(MASTER_UP_FLAG.toLowerCase()) ){
            //主程序启动完成
            return resultStr;
        }
        if( resultStr.toLowerCase().endsWith(MONITOR_FLAG.toLowerCase()) ){
            //monitor启动完成
            return resultStr;
        }


        //重试
        int retryTime=EXEC_REBOOT_RETRY_TIME;
        while( retryTime>0 ){
            resultStr += client.getResponse(EXEC_REBOOT_TIME);
            if( resultStr.toLowerCase().contains(MASTER_UP_FLAG.toLowerCase()) ){
                //主程序启动完成
                return resultStr;
            }
            if( resultStr.toLowerCase().endsWith(MONITOR_FLAG.toLowerCase()) ){
                //monitor启动完成
                return resultStr;
            }

            retryTime--;
        }
        return resultStr;

    }
    public boolean sendSetMac( TelnetClientForCOM client ,String cmd) throws Exception{
        String resultStr = client.sendCommand(cmd, EXEC_MONITOR_MAC_TIME);
        if( resultStr.toLowerCase().contains("sucessful") ){
            return true;
        }



        //重试
        int retryTime=EXEC_MONITOR_MAC_RETRY_TIME;
        while( retryTime>0 ){
            resultStr += client.getResponse(EXEC_MONITOR_MAC_TIME);
            if( resultStr.toLowerCase().contains("sucessful") ){

                return true;
            }


            retryTime--;
        }
        return false;

    }
    public boolean sendSetIP( TelnetClientForCOM client ,String cmd) throws Exception{
        String resultStr = client.sendCommand(cmd, EXEC_MONITOR_IP_TIME);
        if( resultStr.toLowerCase().endsWith(MONITOR_FLAG.toLowerCase()) ){
            return true;
        }



        //重试
        int retryTime=EXEC_MONITOR_IP_RETRY_TIME;
        while( retryTime>0 ){
            resultStr += client.getResponse(EXEC_MONITOR_IP_TIME);
            if( resultStr.toLowerCase().endsWith(MONITOR_FLAG.toLowerCase()) ){

                return true;
            }


            retryTime--;
        }
        return false;

    }

    public boolean sendMonitorFormat( TelnetClientForCOM client ) throws Exception{

        String resultStr = client.sendCommand("y", EXEC_MONITOR_FORMAT_TIME);
        if( resultStr.toLowerCase().endsWith(MONITOR_FLAG.toLowerCase()) ){
            return true;
        }


        //重试
        int retryTime=EXEC_MONITOR_FORMAT_RETRY_TIME;
        while( retryTime>0 ){
            resultStr += client.getResponse(EXEC_MONITOR_FORMAT_TIME);

            if( resultStr.toLowerCase().endsWith(MONITOR_FLAG.toLowerCase()) ){

                return true;
            }

            retryTime--;
        }
        return false;

    }

    public String obtainVerInfo( TelnetClientForCOM client ) throws Exception{

        String resultStr = client.sendCommand("show version", EXEC_SHOW_VER_TIME);
        if( resultStr.endsWith(DEFAULT_AIX_PROMPT) ){
            return resultStr;
        }


        //重试
        int retryTime=EXEC_SHOW_VER_RETRY_TIME;
        while( retryTime>0 ){
            resultStr += client.getResponse(EXEC_SHOW_VER_TIME);

            if( resultStr.endsWith(DEFAULT_AIX_PROMPT) ){

                return resultStr;
            }

            retryTime--;
        }
        return resultStr;

    }

    public boolean endMaster( TelnetClientForCOM client ) throws Exception{

        boolean result=false;
        String resultStr=client.sendCommand("\r\n",EXEC_ENTER_MASTER_TIME);
        if( resultStr.toLowerCase().contains("username:")){
            //有密码时
            return true;
        }
        if(resultStr.endsWith(ENTER_COMMAND_ARROW)){
            //无密码时
            return true;
        }



        //重试
        int retryTime=EXEC_ENTER_MASTER_RETRY_TIME;
        while( retryTime>0 ){
            resultStr = client.sendCommand("\r\n",EXEC_ENTER_MASTER_TIME);;
            if( resultStr.toLowerCase().contains("username:")){
                //有密码时
                return true;
            }
            if(resultStr.endsWith(ENTER_COMMAND_ARROW)){
                //无密码时
                return true;
            }


            retryTime--;
        }
        return result;

    }


    public Result sendPing( TelnetClientForCOM client ,String wantPingIP,String setIP) throws Exception{
        Result result=new Result();
        result.setStatus(false);
        result.setFailedReason("timeout");
        String cmd="ping "+wantPingIP;
        String resultStr = client.sendCommand(cmd, EXEC_PING_TIME);
        if( resultStr.toLowerCase().contains("packet loss") ){
            if(resultStr.toLowerCase().contains("100% packet loss")){
                log.info("setIP["+setIP+"]ping ["+wantPingIP+"] 100% packet loss["+resultStr+"]");
                //ping 失败
                result.setStatus(false);
                result.setFailedReason("Can't ping["+wantPingIP+"]");
                return result;
            }else{
                //ping 成功
                result.setStatus(true);
                if (!resultStr.toLowerCase().contains("0% packet loss")){
                    //有丢包
                    String info=resultStr.split("packets received,")[1];
                    result.setRetMsg(info);
                    //log.info("setIP["+setIP+"]ping ["+wantPingIP+"]packet loss["+info+"]");
                }
                return result;
            }

        }
        if( resultStr.toLowerCase().contains("no answer") ){
            //ping 失败
            log.info("setIP["+setIP+"]ping ["+wantPingIP+"]no answer["+resultStr+"]");
            result.setStatus(false);
            result.setFailedReason("Can't ping["+wantPingIP+"]");
            return result;
        }


        //重试
        int retryTime=EXEC_PING_RETRY_TIME;
        while( retryTime>0 ){
            resultStr += client.getResponse(EXEC_PING_TIME);
            if( resultStr.toLowerCase().contains("packet loss") ){
                if(resultStr.toLowerCase().contains("100% packet loss")){
                    log.info("setIP["+setIP+"]ping ["+wantPingIP+"] 100% packet loss["+resultStr+"]");
                    //ping 失败
                    result.setStatus(false);
                    result.setFailedReason("Can't ping["+wantPingIP+"]");
                    return result;
                }else{
                    //ping 成功
                    result.setStatus(true);
                    if (!resultStr.toLowerCase().contains("0% packet loss")){
                        //有丢包
                        String info=resultStr.split("packets received,")[1];
                        result.setRetMsg(info);
                        //log.info("setIP["+setIP+"]ping ["+wantPingIP+"]packet loss["+info+"]");
                    }
                    return result;
                }

            }
            if( resultStr.toLowerCase().contains("no answer") ){
                log.info("setIP["+setIP+"]ping ["+wantPingIP+"]no answer["+resultStr+"]");
                //ping 失败
                result.setStatus(false);
                result.setFailedReason("Can't ping["+wantPingIP+"]");
                return result;
            }

            retryTime--;
        }
        return result;

    }




    public String sendCommandWithRetryForMonitorUpgrade( TelnetClientForCOM client , long time , int retryTime ,String cmd , List<String> endFlags) throws Exception{
        String resultStr = client.sendCommand(cmd, time);
        for (String endFlag:endFlags){
            String lowerCase = endFlag.toLowerCase();
            if( resultStr.toLowerCase().contains(lowerCase) ){
                return resultStr;
            }
        }
        if(resultStr.endsWith("monitor#")){
            return resultStr;
        }

        //重试
        while( retryTime>0 ){
            resultStr += client.getResponse(time);
            for (String endFlag:endFlags){
                String lowerCase = endFlag.toLowerCase();
                if( resultStr.toLowerCase().contains(lowerCase) ){
                    return resultStr;
                }
            }
            if(resultStr.endsWith("monitor#")){
                return resultStr;
            }

            retryTime--;
        }
        return resultStr;

    }

    /**
     *
     * @param client
     * @return   （Monitor/Master/null) null获取失败
     */
    public String obtainCurrentPattern(TelnetClientForCOM client)  {
        String retStr = null;
        try {
            retStr = connectWithRetry( client , EXEC_CONNECT_TIME , EXEC_RETRY_TIME );
            if(null==retStr){
                return null;
            }
            retStr=client.sendCommand("\r\n",EXEC_ENTER_TIME);
            if(retStr.endsWith(MONITOR_FLAG)){
                return MONITOR_PATTERN;
            }else{
                return MASTER_PATTERN;
            }
        } catch (Exception e) {
            log.error(e.toString());
            return null;
        }finally {
            if(null!=client){
                try {
                    client.disConnect();
                } catch (Exception e) {
                    log.error("close connect error!"+e.toString());
                }
            }
        }

    }

    public boolean isMaster(TelnetClientForCOM client){
        boolean result=false;
        String retStr = null;
        try {
            retStr = connectWithRetry( client , EXEC_CONNECT_TIME , EXEC_RETRY_TIME );
            if(null==retStr){
                log.error("connect ip["+client.getRemoteip()+"]port["+client.getRemoteport()+"]timeout!");
                return result;
            }
            result=endMaster(client);

        } catch (Exception e) {
            log.error("isMaster exception ip["+client.getRemoteip()+"]port["+client.getRemoteport()+"]timeout!"+e.toString());
        }finally {
            if(null!=client){
                try {
                    client.disConnect();
                } catch (Exception e) {
                    log.error(e.toString());
                }
            }
        }
        return result;
    }


    public Result login(String userName, String password, TelnetClientForCOM client,boolean isMonitor) throws Exception {
        Result result=new Result();
        String retStr =connectWithRetry( client , EXEC_CONNECT_TIME , EXEC_RETRY_TIME );
        if(null==retStr){
            result.setStatus(false);
            result.setFailedReason("timeout");
            return result;
        }

        //先回车，才可以输入账号和密码
        retStr=client.sendCommand("\r\n",EXEC_ENTER_TIME);
        if(isMonitor){
            //monitor模式下无需登陆
            result.setStatus(true);
            return result;
        }
        if( retStr.toLowerCase().contains("username")){
            //需要账号密码
            List<String> endFlags=new ArrayList<String>();
            endFlags.add("password");
            String retStr1 = sendCommandWithRetry(client, EXEC_USERPASS_TIME, EXEC_RETRY_TIME, userName, endFlags);
            if( retStr1.toLowerCase().contains("password") ){
                endFlags.clear();
                endFlags.add(ENTER_COMMAND_ARROW);
                retStr1 = sendCommandWithRetry(client, EXEC_USERPASS_TIME, EXEC_RETRY_TIME, password, endFlags);
                if( retStr1.toLowerCase().indexOf(LOGIN_FAILED.toLowerCase())!=-1 ){
                    result.setStatus(false);
                    result.setFailedReason("Username or Password is wrong");
                    result.setRetMsg(retStr1);
                    return result;
                }else{
                    result.setStatus(true);
                    return result;
                }

            }else{
                result.setStatus(false);
                result.setFailedReason("can't see Password");
                result.setRetMsg(retStr1);
                return result;
            }


        }else{
            //设备没有设定账号秘密
            result.setStatus(true);
            return result;
        }


    }
    public Result enableOper(TelnetClientForCOM client,String enablePassword,boolean isMonitor) throws Exception {
        Result result=new Result();
        if(isMonitor){
            //monitor模式下无需enable,
            result.setStatus(true);
            return result;
        }
        String retStr = client.sendCommand("enable", EXEC_ENABLE_TIME);
        if(  retStr.toLowerCase().contains("pass") ){
            retStr = client.sendCommand(enablePassword, EXEC_USERPASS_TIME);
            if( retStr.toLowerCase().indexOf(ACCESS_DENIED.toLowerCase())!=-1 ){
                result.setStatus(false);
                result.setFailedReason("Enable Password is wrong");
                result.setRetMsg(retStr);
                return result;
            }else{
                result.setStatus(true);
                result.setRetMsg(retStr);
                return result;
            }
        }else{
            result.setStatus(true);
            result.setRetMsg(retStr);
            return result;
        }
    }
}
